#include "bmp.h"
#include "../texture.h"
#include <stdlib.h>

namespace sleek
{
    namespace texture
    {
        #define CTOI(C) (*(int*)&C)

        texture* LoadTextureFromBmp(core::os::stringc file)
        {
            FILE *filePtr;
            unsigned char header[0x36];
            int colorMode, imagePos;
            long imageSize, imageIdx, m_width, m_height;
            unsigned char m_bitCount;

            if(!(filePtr = fopen(file.c_str(), "rb"))){ printf("error: couldn't open \"%s\"!\n", file.c_str()); return 0; }
            if(fread(header,1,0x36,filePtr)!=0x36) { printf("error: \"%s\" is not a valid BMP image!\n", file.c_str()); fclose(filePtr); return 0; }
            if(header[0]!='B' || header[1]!='M') { printf("error: Can't find BMP headler in \"%s\"!\n", file.c_str()); fclose(filePtr); return 0; }
            switch(CTOI(header[0x1E]))
            {
                case 0: case 1: case 2: case 3: break;
                default: printf("error: \"%s\" unsuported compressed mode %d!\n", file.c_str(), CTOI(header[0x1E])); fclose(filePtr); return 0; break;
            }

            printf("Load texture: \"%s\"\n", file.c_str(), CTOI(header[0x1E]));

            m_bitCount = CTOI(header[0x1C]);
            if(m_bitCount == 16) colorMode = TXFMT_RGB;
            else if(m_bitCount == 24) colorMode = TXFMT_RGB;
            else if(m_bitCount == 32) colorMode = TXFMT_RGBA;
            else colorMode = m_bitCount;

            imagePos = CTOI(header[0x0A]);
            imageSize = CTOI(header[0x22]);

            m_width = CTOI(header[0x12]);
            m_height = CTOI(header[0x16]);

            if(!imageSize) imageSize = m_height* m_width*(m_bitCount/8);
            if(!imagePos) imagePos = 0x36;

            fseek(filePtr,imagePos,0);
            texture *bmp = new texture(core::math::vector2du(m_width, m_height), (TextureFormat)colorMode);

            if (!bmp->buffer) { fclose(filePtr); printf("texture: alocation fail\n"); return 0; }
            if(fread(bmp->buffer,1,imageSize,filePtr) != (unsigned long)imageSize);
            fclose(filePtr);

            switch(CTOI(header[0x1E]))
            {
                case 0:
                    switch(m_bitCount)
                    {
                        case 16:
                            for (imageIdx = 0; imageIdx < imageSize; imageIdx += colorMode) // bgr >> rgb
                            {
                                unsigned char colorSwap = bmp->buffer[imageIdx];
                                bmp->buffer[imageIdx]   = bmp->buffer[imageIdx+2];//2
                                bmp->buffer[imageIdx+1] = bmp->buffer[imageIdx+1];//1
                                bmp->buffer[imageIdx+2] = colorSwap;
                            }
                        break;
                        case 24:
                            for (imageIdx = 0; imageIdx < imageSize; imageIdx += colorMode) // bgr >> rgb
                            {
                                unsigned char colorSwap = bmp->buffer[imageIdx];
                                bmp->buffer[imageIdx]   = bmp->buffer[imageIdx+2];//2
                                bmp->buffer[imageIdx+1] = bmp->buffer[imageIdx+1];//1
                                bmp->buffer[imageIdx+2] = colorSwap;
                            }
                        break;
                        case 32:
                            for (imageIdx = 0; imageIdx < imageSize; imageIdx += colorMode) // bgr >> rgb
                            {
                                unsigned char colorSwap = bmp->buffer[imageIdx];
                                bmp->buffer[imageIdx]   = bmp->buffer[imageIdx+2];//2
                                bmp->buffer[imageIdx+1] = bmp->buffer[imageIdx+1];//1
                                bmp->buffer[imageIdx+3] = bmp->buffer[imageIdx+3];//3
                                bmp->buffer[imageIdx+2] = colorSwap;
                            }
                    }
                break;
                case 1:
                    //decompress8BitRLE(bmp->buffer, imageSize, m_width, m_height, colorMode);
                break;
                case 2:
                    //decompress4BitRLE(bmp->buffer, imageSize, m_width, m_height, colorMode);
                break;
                case 3:
                    switch(m_bitCount)
                    {
                        case 32:
                            for (imageIdx = 0; imageIdx < imageSize; imageIdx += colorMode) // xrgb -> rgb(a = 255)
                            {
                                unsigned char colorSwap = bmp->buffer[imageIdx+2];
                                bmp->buffer[imageIdx]   = bmp->buffer[imageIdx+3];
                                bmp->buffer[imageIdx+2] = bmp->buffer[imageIdx+1];
                                bmp->buffer[imageIdx+1] = colorSwap;
                                bmp->buffer[imageIdx+3] = 255;
                            }
                        break;
                        default: break;
                    }
                break;
            }

            bmp->GenerateGlTexture();
            return bmp;
        }
        bool WriteTextureToBmp(texture *img,core::os::stringc file)
        {
            FILE *filePtr;
            if (!(filePtr = fopen(file.c_str(), "wb+")) && !img){ printf("error: couldn't open \"%s\"!\n", file.c_str()); return false; }
            else printf("Write texture: \"%s\"\n", file.c_str());

            unsigned char header[0x36];
                header[0] = 'B';
                header[1] = 'M';
                header[0x1E] = 1;
                header[0x1C] = img->getFormat()*8;
            fwrite(header,1,0x36,filePtr);
            return true;
        }
        bool IsTextureFormatBmp(core::os::stringc file)
        {
            FILE *filePtr;
            unsigned char header[2];
            if (!(filePtr = fopen(file.c_str(), "rb"))){  printf("error: couldn't open \"%s\"!\n", file.c_str()); return 0; }
            if (fread(header,1,2,filePtr)!=2) { fclose(filePtr); return 0; }
            if (header[0]!='B' || header[1]!='M') { fclose(filePtr); return 0; }
            return true;
        }
    }
}

